package com.pulse.common.utils.sor;

import com.pulse.common.utils.sor.domain.Block;
import com.pulse.common.utils.sor.domain.DataPtsParams;
import com.pulse.common.utils.sor.domain.DataPtsVo;
import com.pulse.common.utils.sor.domain.SorInfo;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DataPts {
    /**
     * 处理 DataPts 块
     *
     * @param fh        输入流
     * @param sorInfo   存储结果的字典
     * @return 状态字符串
     */
    public static String process(BufferedInputStream fh, SorInfo sorInfo) {
        final String bname = "DataPts";
        int hsize = bname.length() + 1; // 包括尾部的 '\0'
        Block refBlock = null;
        String status = "nok";

        try {
            // 获取块的引用
            refBlock = sorInfo.getBlocks().getDataPts();
            long startpos = (long) refBlock.getPos();
            fh.reset();
            fh.skip(startpos);  // 跳过块的起始位置
        } catch (Exception ex) {
            return status;
        }

        int format = (int) sorInfo.getFormat();

        if (format == 2) {
            // 读取并验证头部
            byte[] buffer = new byte[hsize];
            try {
                fh.read(buffer, 0, hsize);
            } catch (IOException e) {
                return status;
            }
            String mystr = new String(buffer, StandardCharsets.US_ASCII);
            if (!mystr.equals(bname + "\0")) {
                return status;
            }
        }

        // 初始化 DataPts 字典
        sorInfo.setDataPts(new DataPtsVo());
        DataPtsVo xref = sorInfo.getDataPts();

        // 额外参数
        DataPtsParams dataptsParams = new DataPtsParams();
        dataptsParams.setXscaling(1d);
        dataptsParams.setOffset("STV");
        xref.setDataPtsParams(dataptsParams);

        // 处理数据
        try {
            status = processData(fh, sorInfo);
        } catch (IOException e) {
            return status;
        }

        // 读取块的剩余部分（如果需要）
        long endpos = (long) sorInfo.getBlocks().getDataPts().getPos()
                + (long) sorInfo.getBlocks().getDataPts().getSize();

        try {
            fh.skip(endpos - fh.available());
        } catch (IOException e) {
            return status;
        }

        status = "ok";
        return status;
    }

    /**
     * 处理数据
     */
    private static String processData(BufferedInputStream fh, SorInfo sorInfo) throws IOException {
        final String bname = "DataPts";
        DataPtsVo xref = sorInfo.getDataPts();

        String model = "";
        try {
            // 假设 SupParams 块已经处理
            model = sorInfo.getSupParams().getOtdr();
        } catch (Exception ex) {
            // 忽略异常
        }

        // 特殊情况：OFL250 模型需要调整缩放因子
        if (model.equals("OFL250")) {
            xref.getDataPtsParams().setXscaling(0.1);
        }

        // 读取数据点数量
        long N = Parts.getUInt(fh, 4);
        if (N != (long)Double.parseDouble(sorInfo.getFxdParams().getNumDataPoints())) {
            // 数据点数量不匹配
        }

        xref.setNumDataPoints(N);

        // 读取跟踪数量
        int numTraces = (int) Parts.getSigned(fh, 2);
        xref.setNumTraces((long)numTraces);

        if (numTraces > 1) {
            System.exit(1); // 退出程序
        }

        // 再次读取数据点数量
        long numDataPoints2 = Parts.getUInt(fh, 4);
        xref.setNumDataPoints2(numDataPoints2);

        // 读取缩放因子
        int scalingFactorRaw = (int) Parts.getUInt(fh, 2);
        double scalingFactor = scalingFactorRaw / 1000.0;
        xref.setScalingFactor(scalingFactor);

        // 读取数据点
        List<Integer> dlist = new ArrayList<>();
        for (int i = 0; i < N; i++) {
            int val = (int) Parts.getUInt(fh, 2);
            dlist.add(val);
        }

        // 计算最大值和最小值
        int ymax = dlist.stream().max(Integer::compare).orElse(0);
        int ymin = dlist.stream().min(Integer::compare).orElse(0);
        double fs = 0.001 * scalingFactor;
        String dispMin = String.format("%.3f", ymin * fs);
        String dispMax = String.format("%.3f", ymax * fs);
        xref.setMaxBeforeOffset(Double.parseDouble(dispMax));
        xref.setMinBeforeOffset(Double.parseDouble(dispMin));

        // 应用偏移并保存到 tracedata
        String offset = xref.getDataPtsParams().getOffset();
        double xscaling = xref.getDataPtsParams().getXscaling();
        double dx = sorInfo.getFxdParams().getResolution();

        List<Double> nlist = new ArrayList<>();
        if (offset.equals("STV")) {
            for (Integer val : dlist) {
                nlist.add((ymax - val) * fs);
            }
        } else if (offset.equals("AFL")) {
            for (Integer val : dlist) {
                nlist.add((ymin - val) * fs);
            }
        } else {
            for (Integer val : dlist) {
                nlist.add(-val * fs);
            }
        }

        xref.setTracedata(new ArrayList<>());
        List<String> tracedata = xref.getTracedata();
        for (int i = 0; i < N; i++) {
            double x = dx * i * xscaling / 1000.0; // 输出单位为 km
            tracedata.add(String.format("%.6f\t%.6f", x, nlist.get(i)));
        }

        return "ok";
    }
}
